
package w83a.xml;

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.DOMSource;

import w83a.xml.exception.W83AXmlErrorCodes;
import w83a.xml.exception.W83AXmlException;



/**
 * Permite efectuar transformaciones de una fuente xml. <br>
 * <br>
 * El producto de una transformación se denomina resultado. Una transformación
 * puede utilizar o no instrucciones xsl.
 */

public final class W83AXmlTransformer implements java.io.Serializable{

	private static final long serialVersionUID = 1L;
   private Transformer transformer;

   private Source source;

   /** Construye un objeto de la clase. */

   public W83AXmlTransformer() {

      transformer = null;
      source = null;
   }

   /**
    * Crea un transformador sin instrucciones xsl.
    * 
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public void create() throws W83AXmlException {

      TransformerFactory fry;

      fry = TransformerFactory.newInstance();

      try {
         transformer = fry.newTransformer();
      }
      catch (Exception exc) {
         throw new W83AXmlException(W83AXmlErrorCodes.EC_TRANSFORM_EXCEPTION,
                  exc);
      }

   }

   /**
    * Crea un transformador con instrucciones xsl.
    * 
    * @param pathname
    *           Ruta de acceso y nombre del fichero xsl con las instrucciones.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public void createUsingXslFile(String pathname) throws W83AXmlException {

      TransformerFactory fry;
      StreamSource xsl;

      fry = TransformerFactory.newInstance();
      xsl = new StreamSource(new File(pathname));

      try {
         transformer = fry.newTransformer(xsl);
      }
      catch (Exception exc) {
         throw new W83AXmlException(W83AXmlErrorCodes.EC_TRANSFORM_EXCEPTION,
                  exc);
      }

   }

   /**
    * Crea un transformador con instrucciones xsl.
    * 
    * @param pathname
    *           Ruta de acceso y nombre del fichero xsl con las instrucciones.
    * @throws W83AXmlException, IOException
    *            si se produce algún error.
    */

   public void createUsingXslResourceFile(String pathname)
            throws W83AXmlException, IOException {

      TransformerFactory fry;
      StreamSource xsl;
      InputStream inputStream = null;

      try {
         fry = TransformerFactory.newInstance();
         inputStream = ClassLoader.getSystemResourceAsStream(pathname);
         xsl = new StreamSource(inputStream);
         transformer = fry.newTransformer(xsl);
      }
      catch (Exception exc) {
         throw new W83AXmlException(W83AXmlErrorCodes.EC_TRANSFORM_EXCEPTION,
                  exc);
      }
      finally {
         if (inputStream != null){
        	 inputStream.close();
         }
      }

   }

   /**
    * Crea un transformador con instrucciones xsl.
    * 
    * @param text
    *           Texto xsl con las instrucciones.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public void createUsingXslStringText(String text) throws W83AXmlException {

      TransformerFactory fry;
      StreamSource xsl;

      fry = TransformerFactory.newInstance();
      xsl = new StreamSource(new StringReader(text));

      try {
         transformer = fry.newTransformer(xsl);
      }
      catch (Exception exc) {
         throw new W83AXmlException(W83AXmlErrorCodes.EC_TRANSFORM_EXCEPTION,
                  exc);
      }

   }

   /**
    * Crea un transformador con instrucciones xsl.
    * 
    * @param text
    *           Texto xsl, codificado en UTF-8, con las instrucciones.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public void createUsingXslUtf8Text(byte[] text) throws W83AXmlException {

      TransformerFactory fry;
      StreamSource xsl;

      fry = TransformerFactory.newInstance();
      xsl = new StreamSource(new ByteArrayInputStream(text));

      try {
         transformer = fry.newTransformer(xsl);
      }
      catch (Exception exc) {
         throw new W83AXmlException(W83AXmlErrorCodes.EC_TRANSFORM_EXCEPTION,
                  exc);
      }

   }

   /**
    * Crea un transformador con instrucciones xsl.
    * 
    * @param doc
    *           Documento xsl con las instrucciones.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   /*
    * NO FUNCIONA public void createUsingXslDocument(W83AXmlDocument doc) throws
    * W83AXmlException {
    * 
    * TransformerFactory fry; DOMSource xsl;
    * 
    * fry = TransformerFactory.newInstance(); xsl = new
    * DOMSource(doc.getDomDocument()); transformer = fry.newTransformer(xsl); }
    */

   /**
    * Establece la fuente de la transformación.
    * 
    * @param pathname
    *           Ruta de acceso y nombre del fichero xml con la fuente.
    */

   public void setSourceFromXmlFile(String pathname) {

      source = new StreamSource(new File(pathname));
   }

   /**
    * Establece la fuente de la transformación.
    * 
    * @param text
    *           Texto xml con la fuente.
    */

   public void setSourceFromXmlStringText(String text) {

      source = new StreamSource(new StringReader(text));
   }

   /**
    * Establece la fuente de la transformación.
    * 
    * @param text
    *           Texto xml, codificado en UTF-8, con la fuente.
    */

   public void setSourceFromXmlUtf8Text(byte[] text) {

      source = new StreamSource(new ByteArrayInputStream(text));
   }

   /**
    * Establece la fuente de la transformación.
    * 
    * @param doc
    *           Documento xml con la fuente.
    */

   public void setSourceFromXmlDocument(W83AXmlDocument doc) {

      source = new DOMSource(doc.getDomDocument());
   }

   /**
    * Establece la fuente de la transformación.
    * 
    * @param elem
    *           Elemento xml con la fuente.
    */

   public void setSourceFromXmlElement(W83AXmlElement elem) {

      source = new DOMSource(elem.getDomElement());
   }

   /**
    * Efectúa la transformación.
    * 
    * @return Texto con el resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public String transformToStringText() throws W83AXmlException {

      StreamResult res;
      StringWriter resWriter;

      resWriter = new StringWriter();
      res = new StreamResult(resWriter);

      try {
         transformer.transform(source, res);
      }
      catch (Exception exc) {
         throw new W83AXmlException(W83AXmlErrorCodes.EC_TRANSFORM_EXCEPTION,
                  exc);
      }

      return resWriter.toString();

   }

   /**
    * Efectúa la transformación.
    * 
    * @return Texto, codificado en UTF-8, con el resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public byte[] transformToUtf8Text() throws W83AXmlException {

      StreamResult res;
      ByteArrayOutputStream resStream;

      resStream = new ByteArrayOutputStream();
      res = new StreamResult(resStream);

      try {
         transformer.transform(source, res);
      }
      catch (Exception exc) {
         throw new W83AXmlException(W83AXmlErrorCodes.EC_TRANSFORM_EXCEPTION,
                  exc);
      }

      return resStream.toByteArray();

   }

   /**
    * Efectúa la transformación.
    * 
    * @param pathname
    *           Ruta de acceso y nombre del fichero en el que se almacena el
    *           resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public void transformToFile(String pathname) throws W83AXmlException {

      StreamResult res;

      res = new StreamResult(new File(pathname));

      try {
         transformer.transform(source, res);
      }
      catch (Exception exc) {
         throw new W83AXmlException(W83AXmlErrorCodes.EC_TRANSFORM_EXCEPTION,
                  exc);
      }

   }

   /**
    * Permite especificar si en el resultado de una transformación se omite la
    * declaración Xml.
    * 
    * @param omit
    *           Especifica si omitir la declaración xml.
    */

   public void setOmitXmlDeclarationInOutput(boolean omit) {

      String text;

      if (omit)
      {
    	  text = "yes";
      }
      else
      {
    	  text = "no";
      }

      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, text);

   }

   /** Permite especificar que el resultado de una transformación es xml. */

   public void setXmlOutputMethod() {

      transformer.setOutputProperty(OutputKeys.METHOD, "xml");
   }

   /** Permite especificar que el resultado de una transformación es html. */

   public void setHtmlOutputMethod() {

      transformer.setOutputProperty(OutputKeys.METHOD, "html");
   }

   /**
    * Efectúa la transformación de una fuente xml sin utilizar instrucciones
    * xsl.
    * 
    * @param xmlDoc
    *           Documento xml con la fuente.
    * @param omitXmlHdr
    *           Especifica si omitir la cabecera xml en el resultado.
    * @return Texto xml con el resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static String transformXmlDocumentToXmlStringText(W83AXmlDocument xmlDoc,
            boolean omitXmlHdr) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.create();
      transformer.setSourceFromXmlDocument(xmlDoc);
      transformer.setOmitXmlDeclarationInOutput(omitXmlHdr);

      return transformer.transformToStringText();

   }

   /**
    * Efectúa la transformación de una fuente xml sin utilizar instrucciones
    * xsl.
    * 
    * @param xmlDoc
    *           Documento xml con la fuente.
    * @param omitXmlHdr
    *           Especifica si omitir la cabecera xml en el resultado.
    * @return Texto xml, codificado en UTF-8, con el resultado de la
    *         transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static byte[] transformXmlDocumentToXmlUtf8Text(W83AXmlDocument xmlDoc,
            boolean omitXmlHdr) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.create();
      transformer.setSourceFromXmlDocument(xmlDoc);
      transformer.setOmitXmlDeclarationInOutput(omitXmlHdr);

      return transformer.transformToUtf8Text();

   }

   /**
    * Efectúa la transformación de una fuente xml sin utilizar instrucciones
    * xsl.
    * 
    * @param xmlDoc
    *           Documento xml con la fuente.
    * @param filePathName
    *           Ruta de acceso y nombre del fichero en el que se almacena el
    *           resultado xml de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static void transformXmlDocumentToXmlFile(W83AXmlDocument xmlDoc,
            String filePathName) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.create();
      transformer.setSourceFromXmlDocument(xmlDoc);

      transformer.transformToFile(filePathName);

   }

   /**
    * Efectúa la transformación de una fuente xml sin utilizar instrucciones
    * xsl.
    * 
    * @param xmlElem
    *           Elemento xml con la fuente.
    * @param omitXmlHdr
    *           Especifica si omitir la cabecera xml.
    * @return Texto xml con el resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static String transformXmlElementToXmlStringText(W83AXmlElement xmlElem,
            boolean omitXmlHdr) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.create();
      transformer.setSourceFromXmlElement(xmlElem);
      transformer.setOmitXmlDeclarationInOutput(omitXmlHdr);

      return transformer.transformToStringText();

   }

   /**
    * Efectúa la transformación de una fuente xml sin utilizar instrucciones
    * xsl.
    * 
    * @param xmlElem
    *           Elemento xml con la fuente.
    * @param omitXmlHdr
    *           Especifica si omitir la cabecera xml.
    * @return Texto xml, codificado en UTF-8, con el resultado de la
    *         transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static byte[] transformXmlElementToXmlUtf8Text(W83AXmlElement xmlElem,
            boolean omitXmlHdr) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.create();
      transformer.setSourceFromXmlElement(xmlElem);
      transformer.setOmitXmlDeclarationInOutput(omitXmlHdr);

      return transformer.transformToUtf8Text();

   }

   /**
    * Efectúa la transformación de una fuente xml utilizando instrucciones xsl.
    * 
    * @param xmlDoc
    *           Documento xml con la fuente.
    * @param xslFilePathName
    *           Ruta de acceso y nombre del fichero xsl con las instrucciones.
    * @return Texto html con el resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static String transformXmlDocumentToHtmlStringTextUsingXslFile(W83AXmlDocument xmlDoc,
            String xslFilePathName) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.createUsingXslFile(xslFilePathName);
      transformer.setSourceFromXmlDocument(xmlDoc);
      transformer.setHtmlOutputMethod();

      return transformer.transformToStringText();

   }

   public static byte[] transformXmlDocumentToHtmlUtf8TextUsingXslFile(W83AXmlDocument xmlDoc,
            String xslFilePathName) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.createUsingXslFile(xslFilePathName);
      transformer.setSourceFromXmlDocument(xmlDoc);
      transformer.setHtmlOutputMethod();

      return transformer.transformToUtf8Text();

   }

   /**
    * Efectúa la transformación de una fuente xml utilizando instrucciones xsl.
    * 
    * @param xmlDoc
    *           Documento xml con la fuente.
    * @param xslFilePathName
    *           Ruta de acceso y nombre del fichero xsl con las instrucciones.
    * @return Texto html con el resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static String transformXmlUtf8ToHtmlStringTextUsingXslFile(byte[] xmlDoc,
            String xslFilePathName) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.createUsingXslFile(xslFilePathName);
      transformer.setSourceFromXmlUtf8Text(xmlDoc);
      transformer.setHtmlOutputMethod();

      return transformer.transformToStringText();

   }

   /**
    * Efectúa la transformación de una fuente xml utilizando instrucciones xsl.
    * 
    * @param xmlDoc
    *           Documento xml con la fuente.
    * @param xslDoc
    *           Contenido del documento xsl con las instrucciones.
    * @return Texto html con el resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static String transformXmlUtf8ToHtmlStringTextUsingXslText(byte[] xmlDoc,
            String xslDoc) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.createUsingXslStringText(xslDoc);
      transformer.setSourceFromXmlUtf8Text(xmlDoc);
      transformer.setHtmlOutputMethod();

      return transformer.transformToStringText();

   }

   /**
    * Efectúa la transformación de una fuente xml utilizando instrucciones xsl.
    * 
    * @param xmlDoc
    *           Documento xml con la fuente.
    * @param xslFilePathName
    *           Ruta de acceso y nombre del fichero xsl con las instrucciones.
    * @return Texto html con el resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static String transformXmlUtf8ToHtmlStringTextUsingXslResourceFile(byte[] xmlDoc,
            String xslFilePathName) throws W83AXmlException, IOException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.createUsingXslResourceFile(xslFilePathName);
      transformer.setSourceFromXmlUtf8Text(xmlDoc);
      transformer.setHtmlOutputMethod();

      return transformer.transformToStringText();

   }

   public static byte[] transformXmlStringToHtmlUtf8TextUsingXslFile(String xmlDoc,
            String xslFilePathName) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.createUsingXslFile(xslFilePathName);
      transformer.setSourceFromXmlStringText(xmlDoc);
      transformer.setHtmlOutputMethod();

      return transformer.transformToUtf8Text();

   }

   /**
    * Efectúa la transformación de una fuente xml utilizando instrucciones xsl.
    * 
    * @param xmlFilePathName
    *           Ruta de acceso y nombre del fichero xml con la fuente.
    * @param xslFilePathName
    *           Ruta de acceso y nombre del fichero xsl con las instrucciones.
    * @return Texto html con el resultado de la transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static String transformXmlFileToHtmlStringTextUsingXslFile(String xmlFilePathName,
            String xslFilePathName) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.createUsingXslFile(xslFilePathName);
      transformer.setSourceFromXmlFile(xmlFilePathName);
      transformer.setHtmlOutputMethod();

      return transformer.transformToStringText();

   }

   /**
    * Efectúa la transformación de una fuente xml utilizando instrucciones xsl.
    * 
    * @param xmlFilePathName
    *           Ruta de acceso y nombre del fichero xml con la fuente.
    * @param xslFilePathName
    *           Ruta de acceso y nombre del fichero xsl con las instrucciones.
    * @return Texto html, codificado en UTF-8, con el resultado de la
    *         transformación.
    * @throws W83AXmlException
    *            si se produce algún error.
    */

   public static byte[] transformXmlFileToHtmlUtf8TextUsingXslFile(String xmlFilePathName,
            String xslFilePathName) throws W83AXmlException {

      W83AXmlTransformer transformer;

      transformer = new W83AXmlTransformer();

      transformer.createUsingXslFile(xslFilePathName);
      transformer.setSourceFromXmlFile(xmlFilePathName);
      transformer.setHtmlOutputMethod();

      return transformer.transformToUtf8Text();

   }

} // class XmlTransformer
